<?php
namespace App\Http\Controllers\Api\Buz;

use App\Http\Controllers\Controller;
use App\Jobs\DoRegisterEmail;
use App\Jobs\PasswordResetEmail;
use App\Lib\Code;
use App\Models\PasswordReset;
use App\Models\PlatUser;
use App\Models\PlatUserTmp;
use App\Models\RechargeGroup;
use App\Models\SettleGroup;
use App\Repositories\Contracts\PlatUserRepository;
use App\Services\ApiResponseService;
use App\Validators\Buz\AuthValidator;
use Carbon\Carbon;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config;
use Prettus\Validator\Exceptions\ValidatorException;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Facades\JWTAuth;

class AuthController extends Controller
{
    use DispatchesJobs;
    protected $authValidator;

    public function __construct(AuthValidator $authValidator)
    {
        $this->authValidator = $authValidator;
    }

    public function login(Request $request)
    {
        $this->authValidator->with($request->all())->passesOrFail('login');
        $credentials = $request->only('username', 'password');
        $token = null;
        try {
            if ( ! $token = JWTAuth::attempt($credentials)) {
                return ApiResponseService::showError(Code::LOGIN_INVALID);
            }
        } catch (JWTException $jwt) {
            return ApiResponseService::showError(Code::JWT_ERROR);
        }
        $user = Auth::user();
        $user->last_at = Carbon::now()->toDateTimeString();
        $user->last_ip = $request->getClientIp();
        $user->save();
        \Session::put('user', $user);
        $user = [
            'id' => $user->id,
            'username' => $user->username,
            'last_at' => $user->last_at,
            'last_ip' => $user->last_ip,
            'is_profiled' => $user->is_profiled,
            'is_remitted' => $user->is_remitted
        ];
        return ApiResponseService::returnData(compact('token', 'user'));
    }


    public function register(Request $request)
    {
        $tmp = $request->only('username', 'phone');
        $user = PlatUser::where('username', $tmp['username'])
            ->orWhere('phone', $tmp['phone'])
            ->first();
        if ($user) return ApiResponseService::showError(Code::REGISTER_USER_EXISTS);
        $expired_at = time() + 24 * 60;
        $token = md5($expired_at . $tmp['username'] . $tmp['phone']);
        $reg_ip = $request->getClientIp();
        $tmp += compact('token', 'expired_at', 'reg_ip');
        $tmpUser = PlatUserTmp::where('username', $tmp['username'])
            ->orWhere('phone', $tmp['phone'])
            ->first();
        if (! $tmpUser) {
            $tmpUser = PlatUserTmp::create($tmp);
        } else {
            $tmpUser->update($tmp);
        }
        $this->dispatch(new DoRegisterEmail($tmpUser));
        return ApiResponseService::success(Code::SUCCESS);
    }

    public function doRegister(Request $request)
    {
        $data = $request->all(array_keys($this->authValidator->getRules('register')));
        try {
            $this->authValidator->with($data)->passesOrFail('register');
            $userTmp = PlatUserTmp::where('token', $data['token'])->first();
            if ( ! $userTmp) {
                return ApiResponseService::showError(Code::REGISTER_TOKEN_INVALID);
            }
            //获取默认分组
            $defaultRechargeGroup = RechargeGroup::byDefault()->byBuz()->first();
            $defaultSettleGroup = SettleGroup::byDefault()->byBuz()->first();
            $userInfo = $data;
            array_forget($userInfo, 'token');
            $userInfo['username'] = $userTmp['username'];
            $userInfo['password'] = password_hash($userInfo['password'], PASSWORD_DEFAULT);
            $userInfo['trade_pwd'] = password_hash($userInfo['trade_pwd'], PASSWORD_DEFAULT);
            $userInfo['phone'] = $userTmp['phone'];
            $userInfo['reg_ip'] = $userTmp['reg_ip'];
            $userInfo['recharge_gid'] = $defaultRechargeGroup ? $defaultRechargeGroup->id : 0;
            $userInfo['settle_gid'] = $defaultSettleGroup ? $defaultSettleGroup->id : 0;
            if (PlatUser::create($userInfo)) {
                $userTmp->delete();
            }
            return ApiResponseService::success(Code::SUCCESS);
        } catch (ValidatorException $exception) {
            return ApiResponseService::showError(Code::HTTP_REQUEST_PARAM_ERROR, $exception->getMessageBag()->messages());
        } catch (\Exception $exception) {
            return ApiResponseService::showError(Code::FATAL_ERROR, $exception->getMessage());
        }
    }

    public function getAuthUser(Request $request)
    {
        $user = Auth::user();
        $user = [
            'id' => $user->id,
            'role' => $user->profile->role,
            //'id', 'role', 'username', 'status', 'last_at', 'last_ip', 'is_profiled','is_remitted']
            'username' => $user->username,
            'last_at' => $user->last_at,
            'last_ip' => $user->last_ip,
            'is_profiled' => $user->is_profiled,
            'is_remitted' => $user->is_remitted
        ];
        return ApiResponseService::returnData(compact('user'));
    }

    public function loginOut()
    {
        JWTAuth::invalidate(JWTAuth::getToken());
        return ApiResponseService::success(Code::SUCCESS);
    }

    public function forgetPwd(Request $request)
    {
        $credential = $request->all(array_keys($this->authValidator->getRules('forgetPwd')));
        $user = PlatUser::where($credential)->first();
        if ( ! $user) {
            return ApiResponseService::showError(Code::USER_PHONE_NOT_MATCH);
        }
        $token = $credential['username'] . $credential['phone'] . time() . str_random(16);
        $expired = time() + 30 * 60;
        $token = md5($token);
        $reset = PasswordReset::where('email', $credential['username'])->first();
        if (!$reset) {
            $reset = PasswordReset::create([
                'email' => $credential['username'],
                'token' => $token,
                'expired_at' => $expired
                ]);
        } else {
            $reset->update(['token' =>$token, 'expired_at' => $expired]);
        }
        $this->dispatch(new PasswordResetEmail($reset));
        return ApiResponseService::success(Code::SUCCESS);
    }


    public function resetPwd(Request $request)
    {
        $credentials = $request->all(array_keys($this->authValidator->getRules('resetPwd')));
        $this->authValidator->with($credentials)->passesOrFail('resetPwd');
        $passwordReset = PasswordReset::where([
            'email' => $credentials['username'],
            'token' => $credentials['token']
        ])->first();
        if ( ! $passwordReset) {
            return ApiResponseService::showError(Code::FATAL_ERROR, '用户名和认证token不符');
        }
        $user = $passwordReset->platUser;
        $user->password = password_hash($credentials['newpwd'], PASSWORD_DEFAULT);
        if ($user->save()) {
            $passwordReset->delete();
            return ApiResponseService::success(Code::SUCCESS);
        }
    }

}
